package com.bradz.mytv;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.TimerTask;
import java.util.Timer;

import javax.security.auth.callback.Callback;

import org.acra.*;
import org.acra.annotation.*;
import org.json.JSONException;
import org.json.JSONObject;

import com.android.vending.billing.IInAppBillingService;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.IntentSender.SendIntentException;
import android.graphics.Point;
import android.graphics.Typeface;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class activityMain extends Activity {
	
	private classNetworkHolder network;
	private Context self;
	private Typeface font;
	private applicationGlobalVars globals;
	private TextView network_status;
	private ImageView verify_network;
	private Button button_start, button_network_settings;
	private search_network_task asyncTask;
	
	private IInAppBillingService mService;
	private ServiceConnection mServiceConn;
	private classAndroidLogger logger;
	Bundle buyIntentBundle;
	
	//Make sure that the channel offset increment is turned off at the start of the activity
	//Make sure that the shows that are selected from the menu are in alphabetical order
	
	Handler myHandler = new Handler() {

  	    @Override
  	    public void handleMessage(Message msg) {
  	        switch (msg.what) {
	  	        case 0:
	  	        	sent_donation_purchase();
	  	            break;
	  	        default:
	  	            break;
  	        }
  	    }
  	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		logger = new classAndroidLogger("ActivityMain");
		globals = ((applicationGlobalVars) this.getApplication());
		self = this;
		font = Typeface.createFromAsset(getAssets(),"fonts/Neutraface2Text-Book.otf");
		network_status = (TextView)findViewById(R.id.network_status);
		network_status.setTypeface(font);
		
		final classInfoPopUp info_popup = new classInfoPopUp(self,this.getBaseContext(),getAssets(),myHandler);
		//Sends in the image and the display so that the actions can be attached and the popup can be placed correctly
		info_popup.attach_popup_window((ImageView)findViewById(R.id.info_button),getWindowManager().getDefaultDisplay());
		verify_network = (ImageView)findViewById(R.id.network_indicator);
		button_start = (Button) findViewById(R.id.main_button_start);
		button_network_settings = (Button) findViewById(R.id.main_button_network_settings);
		asyncTask = new search_network_task();
		if (!asyncTask.getStatus().equals(AsyncTask.Status.RUNNING)){
    		new search_network_task().execute();
    	}
		bind_billing_activities();
		initialize_buttons();
	}
	
	@Override
    public void onResume(){
    	super.onResume();
    	//This needs to be here so that the network is updated whenever
    	//an activity returns to this activity.
    	if (!asyncTask.getStatus().equals(AsyncTask.Status.RUNNING)){
    		new search_network_task().execute();
    	}
    }
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override
	public void onDestroy() {
	    //stopService(new Intent(this, PayPalService.class));
	    super.onDestroy();
	}
	
	public void initialize_buttons(){
		button_start.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
        		Intent myIntent = new Intent(getBaseContext(), activityMediaPlayer.class);
        		startActivity(myIntent);
            }
        });
		final Button button_channel_settings = (Button) findViewById(R.id.main_button_channel_settings);
		button_channel_settings.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	Intent myIntent = new Intent(getBaseContext(), activityNetworkSettings.class);
        		startActivity(myIntent);
            }
        });
		button_network_settings.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	Intent myIntent = new Intent(getBaseContext(), activityCurrentChannels.class);
        		startActivity(myIntent);
            }
        });
		final Button button_help = (Button) findViewById(R.id.main_button_network_help);
		button_help.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
        		Intent myIntent = new Intent(getBaseContext(), activityHelp.class);
        		startActivity(myIntent);
            }
        });
		button_start.setTypeface(font);
		button_channel_settings.setTypeface(font);
		button_network_settings.setTypeface(font);
		button_help.setTypeface(font);
	}
	
	//Make sure that the network is active and working...
	private class search_network_task extends AsyncTask<Void, Integer, Void> {

		@Override
        protected void onPreExecute() {
			verify_network.setImageDrawable(getResources().getDrawable(R.drawable.object_circle_red));
			verify_network.setVisibility(View.INVISIBLE);
			button_start.setEnabled(false);
			button_network_settings.setEnabled(false);
			button_start.setBackgroundDrawable(getApplicationContext().getResources().getDrawable(R.drawable.button_square_edges_disabled));
			button_network_settings.setBackgroundDrawable(getApplicationContext().getResources().getDrawable(R.drawable.button_square_edges_disabled));
		}
		
		@Override
		protected Void doInBackground(Void... arg0) {
			if(!globals.get_network_loaded()){
				network = new classNetworkHolder(self,true,globals.get_random());
				classChannelDatabase channel_database = network.get_channel_database();
				ArrayList<classChannelHolder> channels = new ArrayList<classChannelHolder>();
				ArrayList<Integer> channel_numbers = new ArrayList<Integer>(channel_database.get_all_channels());
				ArrayList<classRecovery> recovery_table = new ArrayList<classRecovery>(channel_database.get_recovery_table());
				classChannelHolder channel_holder;
				for(int i = 0; i < channel_numbers.size();i++){
					channel_holder = new classChannelHolder(channel_numbers.get(i), 
							channel_database.get_channel_name(channel_numbers.get(i)), 
							channel_database.get_channel_paths(channel_numbers.get(i)),true);
					//What is the point of having a channel with no episodes?
					if (channel_holder.channel_size() > 0){
						channels.add(channel_holder);
						//
						if (i<recovery_table.size()){
							channels.get(recovery_table.get(i).channel_number).get_episode(recovery_table.get(i).channel_episode);
							channels.get(recovery_table.get(i).channel_number).set_episode_offset(recovery_table.get(i).episode_offset);
						}
					}
					int progress  = (int) (((i+1) / (float) channel_numbers.size()) * 100);
					Log.i("activityLoadingScreen","Progress: " + String.valueOf(progress) + "%");
					publishProgress(progress);
				}
				network.async_network_update(channels);
            }
			return null;
		}
		
		@Override
		protected void onProgressUpdate(Integer... progress) {
			network_status.setText("Loading: " + String.valueOf(progress[0]) + "%");
			//progressBar.setProgress(progress[0]);
	     }
		
		@Override
	    protected void onPostExecute(Void v) {
			verify_network.setVisibility(View.VISIBLE);
			network_status.setText("Network Status");
			if(!globals.get_network_loaded()){
				globals.set_network_object(network);
				globals.set_network_loaded(true);
			}else{
				network = globals.get_network_object();
			}
			button_network_settings.setEnabled(true);
			button_network_settings.setBackgroundDrawable(getApplicationContext().getResources().getDrawable(R.drawable.selector_edges_button));
			if(!network.network_empty()){
				verify_network.setImageDrawable(getResources().getDrawable(R.drawable.object_circle_green));
				button_start.setEnabled(true);
				button_start.setBackgroundDrawable(getApplicationContext().getResources().getDrawable(R.drawable.selector_edges_button));
			}
		}
	}
	
	public void bind_billing_activities(){
		mServiceConn = new ServiceConnection() {
			   @Override
			   public void onServiceDisconnected(ComponentName name) {
				   logger.info("Billing Service Disconnected...");
				   mService = null;
			   }

			   @Override
			   public void onServiceConnected(ComponentName name, IBinder service) {
				   logger.info("Billing Service Connected...");
				   mService = IInAppBillingService.Stub.asInterface(service);
			   }
		};
		bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE);
	}
	
	public void sent_donation_purchase(){
		classDeveloperPayload payload = new classDeveloperPayload();
    	
    	LoadBillingTask task = new LoadBillingTask(payload.get_payload(), "mytv_donation");
    	
    	task.run();
	}
	
    class LoadBillingTask extends TimerTask {
        private Handler mHandler = new Handler(Looper.getMainLooper());
		String payload;
		String item_name;

        LoadBillingTask(String payload, String item_name){
        	logger.info("Init Billing");
  			this.payload = payload;
  			this.item_name = item_name;
  			logger.info("Done Init Billing");
        }
        
        @Override
        public void run() {
           mHandler.post(new Runnable() {
              public void run() {
            	  try {
            		  logger.info("Starting runnable");
            		  logger.info("package: " + getPackageName());
            		  logger.info("item: " + item_name);
            		  logger.info("payload: " + payload);
            		if(mService == null){
            			logger.info("mService: invalid");
            			logger.toast("There was a problem connecting to the billing service", self);
            		}else{
            			logger.info("mService: valid");
            			buyIntentBundle = mService.getBuyIntent(3, getPackageName(), item_name, "inapp", payload);
            			logger.info("Intent info");
            			if(buyIntentBundle.getInt("RESPONSE_CODE") != 7){
	            			logger.info("Starting pending intent");
	            			
	          				PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
	          				
	          				logger.info("Starting sender for result");
	          				startIntentSenderForResult(pendingIntent.getIntentSender(),
	          					   1641, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
	          					   Integer.valueOf(0));
            			}else{
            				logger.toast("This product has already been purchased!", self);
            			}
            		}
      			} catch (RemoteException e) {
      				logger.error(e.toString());
      				e.printStackTrace();
      			} catch (SendIntentException e) {
      				logger.error(e.toString());
      				e.printStackTrace();
      			} catch (Exception e){
      				logger.error(e.toString());
      				e.printStackTrace();
      			}
              }
           });
         }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)    
    {
        super.onActivityResult(requestCode, resultCode, data);
        logger.info("RequestCode: " + requestCode);
        logger.info("ResultCode: " + resultCode);
        if (requestCode == 1641 && resultCode == Activity.RESULT_OK) {           
        	logger.info("onactivity result called inside request code");
            try{
            	
            	logger.info("Parsing response data");
	            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
	            logger.info("ResponseCode: " + responseCode);
	            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
	            logger.info("purchaseData: " + purchaseData);
	            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
	            logger.info("dataSignature: " + dataSignature);
	            
	            
	            if (responseCode == Constants.BILLING_RESPONSE_RESULT_OK) {
	                try {
    	                JSONObject jo = new JSONObject(purchaseData);
    	                String sku = jo.getString("productId");
    	                logger.info("productId: " + sku);
    	                //This is where the purchase needs to actually be put into the system...
    	                
    	                JSONObject o = new JSONObject(purchaseData);
    	                logger.info("Purchase Data: " + o.toString());
    	                String mOrderId = o.optString("orderId");
    	                logger.info("mOrderId: " + mOrderId);
    	                String mPackageName = o.optString("packageName");
    	                logger.info("mPackageName: " + mPackageName);
    	                String mSku = o.optString("productId");
    	                logger.info("mSku: " + mSku);
    	                long mPurchaseTime = o.optLong("purchaseTime");
    	                logger.info("purchaseTime: " + mPurchaseTime);
    	                int mPurchaseState = o.optInt("purchaseState");
    	                logger.info("mPurchaseState: " + mPurchaseState);
    	                String mDeveloperPayload = o.optString("developerPayload");
    	                logger.info("mDeveloperPayload: " + mDeveloperPayload);
    	                String mToken = o.optString("token", o.optString("purchaseToken"));
    	                logger.info("mToken: " + mToken);
    	                
    	                //Need to consume the purchase before returning
    	                try {
    	                    mService.consumePurchase(3, getPackageName(), mToken);
    	                } catch (RemoteException e) {
    	                	logger.error(e.toString());
    	                    e.printStackTrace();
    	                }
    	                
    	                //This is the method that reflects back to the prototype
                		Object[] parameterTypes = new Object[2];
                        parameterTypes[0] = Integer.valueOf(o.optString("developerPayload").split(">>>")[0]);
                        parameterTypes[1] = mToken;
                		
    					try {
	    	                logger.toast("Thank you for your donation! Now we can afford to eat tonight!", self);
    						
    					} catch (IllegalArgumentException e) {
    						// TODO Auto-generated catch block
    						logger.error(e.toString());
    						e.printStackTrace();
    					} 
	                }catch (JSONException e) {
	                            Toast.makeText(this, "Failed to parse purchase data.", Toast.LENGTH_SHORT);
	                            logger.error(e.toString());
	                            e.printStackTrace();
	                }
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_USER_CANCELED) {
	                	logger.error("User cancelled purchase"); 
	                	Toast.makeText(this, "User cancelled purchase.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE) {
	                	logger.error("Your Device doesn't support inapp billing"); 
	                	Toast.makeText(this, "Your Device doesn't support inapp billing.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE) {
	                	logger.error("Item is not available for billing"); 
	                	Toast.makeText(this, "Item is not available for billing", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_DEVELOPER_ERROR) {
	                	logger.error("Can't purchase item due to some developer error"); 
	                	Toast.makeText(this, "Can't purchase item due to some developer error.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ERROR) {
	                	logger.error("Can't purchase item due to some error in response"); 
	                	Toast.makeText(this, "Can't purchase item due to some error in response.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
	                	logger.error("You already own this item"); 
	                	Toast.makeText(this, "You already own this item.", Toast.LENGTH_SHORT).show();
	                }else if (responseCode == Constants.BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED) {
	                	logger.error("You don't own this item");
	                    Toast.makeText(this, "You don't own this item.", Toast.LENGTH_SHORT).show();
	                }
            }catch(Exception e){
            	logger.error(e.toString());
            	logger.error("Unable to make purchase");
            	Toast.makeText(this, "Unable to make purchase.", Toast.LENGTH_SHORT).show();
            }
        }
        
    }
    
    public class Constants{
    	static final int BILLING_RESPONSE_RESULT_OK	= 0;
    	static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
    	static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
    	static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE	= 4;
    	static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;
    	static final int BILLING_RESPONSE_RESULT_ERROR = 6;
    	static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
    	static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
    }
}
